//----------------------------------------------------------------------------------------
//	 OverlapGraph.cc
//
//----------------------------------------------------------------------------------------
// $Id: //CBT-depot/CBT++/src/OverlapGraph.cc#1 $
//----------------------------------------------------------------------------------------
// $Log:$
//========================================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8.........9
//

#include "OverlapGraph.hh"

extern char readbuf[READ_BUFFER_SIZE];


// An edge can be a MatePair Edge.  This is indicated
// by a special bit, and when set this bit indicates to use a different 
// scale factor. 

int Edge::mMatePairScaleFactor;  

//---------------------------------
// * SetMateValues
//---------------------------------
// The goal here is to get an edge in 64 bits.  We can trivially add more info, 
// but to get a basic edge in 64 bits has a number of advantages. 
void 
Edge::SetMateValues(int ti,int span,int score,int le,int re,int dir)
{
  mData0 = 0;
  mData1 = 0;
  
  // Record, then strip the sign. 
  int resign = (re < 0) ? 1:0;
  int lesign = (le < 0) ? 1:0;
  
  re = abs(re);
  le = abs(le);
  
  mData0 = resign << 29;
  mData0 = mData0 | (lesign << 28);
  mData0 = mData0 | (dir << 27);
  mData0 = mData0 | ti;
  
  score = span - score;         // Convert score to a diff
  if (score > 127) score = 127;
  
  // Divide by scale factor
  span = span / mMatePairScaleFactor;
  le = le / mMatePairScaleFactor;
  re = re / mMatePairScaleFactor;
  
  // Fix max. 
  span = (span < 256) ? span:255;
  le = (le < 256) ? le:255;
  re = (re < 256) ? re:255;
  score = (score < 127) ? score:127;
  
  mData1 = score << 24;
  mData1 = mData1 | (le << 16);
  mData1 = mData1 | (span << 8);
  mData1 = mData1 | re;
  
  SetMateEdge();
  
}

//---------------------------------
// * SetValues
//---------------------------------
// The goal here is to get an edge in 64 bits.  We can trivially add more info, 
// but to get a basic edge in 64 bits has a number of advantages. 
void 
Edge::SetValues(int ti,int span,int score,int le,int re,int dir)
{
  mData0 = 0;
  mData1 = 0;
  
  // Record, then strip the sign. 
  int resign = (re < 0) ? 1:0;
  int lesign = (le < 0) ? 1:0;
  
  re = abs(re);
  le = abs(le);
  
  mData0 = resign << 29;
  mData0 = mData0 | (lesign << 28);
  mData0 = mData0 | (dir << 27);
  mData0 = mData0 | ti;
  
  score = span - score;         // Convert score to a diff
  if (score > 127) score = 127;
  
  // Divide by four. 
  span = span >> 2;
  le = le >> 2;
  re = re >> 2;
  
  // Fix max. 
  span = (span < 256) ? span:255;
  le = (le < 256) ? le:255;
  re = (re < 256) ? re:255;
  score = (score < 127) ? score:127;
  
  //cout<<hex;
  //cout<<"span4="<<span<<" le4="<<le<<" re4="<<re<<" scoredelta="<<score<<endl;
  
  mData1 = score << 24;
  mData1 = mData1 | (le << 16);
  mData1 = mData1 | (span << 8);
  mData1 = mData1 | re;

}

//---------------------------------
// * GetValues
//---------------------------------
void 
Edge::GetValues(int &ti,int &span, int &score, int &le, int &re, int &dir)
{
  ti = mData0 & TIMASK;
  dir = (mData0 & DIRMASK) >> 27;
  
  int lesign = mData0 & LESIGNMASK;
  int resign = mData0 & RESIGNMASK;;
  
  re = mData1 & REMASK;
  re = (resign < 0) ? -re:re;
  
  span = (mData1 & SPANMASK) >> 8;
  
  le = (mData1 & LEMASK) >> 16;
  le = (lesign < 0) ? -le:le;
  
  score = (mData1 & SCOREMASK) >> 24;
  
  if (IsMateEdge()){
	 span = span * mMatePairScaleFactor;
	 le = le * mMatePairScaleFactor;
	 re = re * mMatePairScaleFactor;
  }else{
	 span = span << 2;
	 le = le << 2;
	 re = re << 2;	
  }
  
  // restore sign
  le = (lesign==0) ? le:-le;
  re = (resign==0) ? re:-re;
  
  score = span - score;
}  

//------------------------------------------
// * Contains
//------------------------------------------
//
bool 
TIOverlapGraph::Contains(int ti){
  return(mTI2EIdxMap.Contains(ti));
}

//--------------------------------------------
// * GetEdgeTI
//--------------------------------------------
// This kind of graph stores the ti in the edge
// so this method just extracts that.  This method
// is provided to make interface same as for graphs
// that save a nodeIdx in the Edge. 
// 
bool
TIOverlapGraph::GetEdgeTI(Edge * pEdge,int &ti)
{
  ti = pEdge->GetTI();
  return(true);
}


//-------------------------------------------
// * AddEdge
//-------------------------------------------
// Assumes edge is not already in graph
//
void 
TIOverlapGraph::AddEdge(int ti,Edge &Edge){
  int nextEdgeIdx = mEdges.size();
  mEdges.push_back(Edge);
  
  // Record edge location association with ti. 
  mTI2EIdxMap.Add(ti,nextEdgeIdx);
}

//--------------------------------------------
// * AddEdges
//--------------------------------------------
// Assumes edge is not already in graph
//
void 
TIOverlapGraph::AddEdges(int ti,vector<Edge> &Edges){
  vector<int> EdgeIdxs;
  int nextEdgeIdx = mEdges.size();
  int newSize = Edges.size()+mEdges.size();
  mEdges.resize(newSize);

  int idx = 0;
  for(int i = nextEdgeIdx;i < newSize;i++){
	 mEdges[i] = Edges[idx++];
	 EdgeIdxs.push_back(i);
  }

  // Record edge locations association with ti. 
  mTI2EIdxMap.Add(ti,EdgeIdxs);
}

//--------------------------------------------
// * GetEdges
//--------------------------------------------
// Assumes edges exist
//
void 
TIOverlapGraph::GetEdges(int ti,vector<Edge> &Edges){
  // Get a list of the edges
  vector<int> EdgeIdxs;
  mTI2EIdxMap.GetValues(ti,EdgeIdxs);
  
  // Find them and add them to Edges
  for(int i = 0;i< EdgeIdxs.size();i++){
	 Edges.push_back(mEdges[EdgeIdxs[i]]);
  }
}

//--------------------------------------------
// * GetEdges
//--------------------------------------------
// Assumes edges exist
//
void 
TIOverlapGraph::GetEdges(int ti,vector<Edge*> &EdgePtrs){
  // Get a list of the edges
  vector<int> EdgeIdxs;
  mTI2EIdxMap.GetValues(ti,EdgeIdxs);
  
  // Find them and add them to Edges
  for(int i = 0;i< EdgeIdxs.size();i++){
	 int edgeIdx = EdgeIdxs[i];
	 Edge * pE = &(mEdges[edgeIdx]);
	 EdgePtrs.push_back(pE);
  }
}

//-------------------------------------------
// * AddEdges
//-------------------------------------------
// Assumes edge is not already in graph
//
void 
TIOverlapGraph::AddEdges(int ti,vector<Edge> &Edges,vector<Edge*> &EdgePtrs){
  vector<int> EdgeIdxs;
  int nextEdgeIdx = mEdges.size();
  int newSize = Edges.size()+mEdges.size();
  mEdges.resize(newSize);

  int idx = 0;
  for(int i = nextEdgeIdx;i< newSize;i++){
	 mEdges[i] = Edges[idx++];

	 // Return a pointer to the actual edge in the graph. 
	 Edge* pE = &(mEdges[i]);
	 EdgePtrs.push_back(pE);

	 // Save indices of these new edges. 
	 EdgeIdxs.push_back(i);
  }
  
  // Record edge locations association with ti. 
  mTI2EIdxMap.Add(ti,EdgeIdxs);
}


//-----------------------------------------------
// * Read
//-----------------------------------------------
// Adds the edges in the stream to the overlap graph. 
// 
void 
TIOverlapGraph::Read(istream &fin)
{
  // Each iteration through do{} is one line of graph file. 
  do{
	 fin.getline(readbuf,READ_BUFFER_SIZE);
	 string tempLine = readbuf;
	 int offset = 0;
	 
	 int sourceTI = GetNextInteger(tempLine,offset,offset);
	 
	 if (offset >= 0){
		vector<Edge> Edges; 	 
		do{
		  int destTI = GetNextInteger(tempLine,offset,offset);
		  if (offset < 0) continue;
		  
		  // GetNextInteger gets the next integer on the line, which is to say 
		  // it finds the next string of digits (plus possibly a minus sign) 
		  // after offset and extending to the first non-digit, and returns that as an int. 
		  int span = GetNextInteger(tempLine,offset,offset);
		  int score = GetNextInteger(tempLine,offset,offset);
		  int lext = GetNextInteger(tempLine,offset,offset);
		  int rext = GetNextInteger(tempLine,offset,offset);
		  
		  // offset should point to a comma, so next character is the direction. 
		  // Brittle, of course... what if it's comma-space-dir... should maybe be a 
		  // little more cautious. 
		  char dir = tempLine[offset+1];		
		  
		  // consume dir (+1) and bracket (+1) and move one past that (+1)
		  // If this puts us at the end of the line, record that with -1. 
		  offset+=3;
		  if (offset > tempLine.size()) offset = -1;
		  
		  // Add this edge to the list of edges to put in for this sourceName
		  Edge E;
		  E.SetValues(destTI,span,score,lext,rext,dir);
		  Edges.push_back(E);
		  
		}while (offset >= 0);
		
		// Add edges sourceName->e1,e2,e3... to graph. 
		// Also add inverse edges   e1->sourceName e2->sourceName e3->sourceName
		if (Edges.size() > 0){
		  AddEdges(sourceTI,Edges);
		  Edges.clear();
		}
	 }
  }while(!fin.eof());
}


//======================================================================================
//=============================== Mixed Overlap Graph ==================================
//======================================================================================


//-----------------------------------------------
// * GetEdgeTI
//-----------------------------------------------
//
bool
MixedOverlapGraph::GetEdgeTI(Edge * pEdge,int &ti)
{
  int nodeIdx = pEdge->GetTI();
  if (mNodeIdx2TIMap.Contains(nodeIdx)){
	 ti = mNodeIdx2TIMap[nodeIdx];
	 return(true);
  }else{
	 return(false);
  }
}


//-----------------------------------------------
// * GetEdgeName
//-----------------------------------------------
//
bool
MixedOverlapGraph::GetEdgeName(Edge * pEdge,string &name)
{
  int nodeIdx = pEdge->GetTI();
  if (mNodeIdx2NameMap.Contains(nodeIdx)){
	 name = mNodeIdx2NameMap[nodeIdx];
	 return(true);
  }else{
	 return(false);
  }
}



//-----------------------------------------------
// * GetEdgeName
//-----------------------------------------------
//
bool
MixedOverlapGraph::GetEdgeName(Edge &Edge,string &name)
{
  int nodeIdx = Edge.GetTI();
  if (mNodeIdx2NameMap.Contains(nodeIdx)){
	 name = mNodeIdx2NameMap[nodeIdx];
	 return(true);
  }else{
	 return(false);
  }
}

//-----------------------------------------------
// * NameInTargetSet
//-----------------------------------------------
//
bool
MixedOverlapGraph::NameInTargetSet(vector<Edge*> &EdgePtrs,StringSet &TargetNames,
											  string &excludeName,int &foundIdx)
{
  StripWhiteSpace(excludeName); // KJD a little extra paranoia while testing. 

  string EdgeName;
  for(int i = 0;i< EdgePtrs.size();i++){
	 if (GetEdgeName(EdgePtrs[i],EdgeName)){
		StripWhiteSpace(EdgeName);  // KJD paranoia
		bool bEdgeIsExclude = (EdgeName == excludeName);
		if (TargetNames.Contains(EdgeName) && !bEdgeIsExclude){
		  foundIdx = i;
		  return(true);
		}
	 }
  }
  return(false);
}


//-----------------------------------------------
// * NameInTargetSet
//-----------------------------------------------
//
bool
MixedOverlapGraph::NameInTargetSet(vector<Edge> &Edges,StringSet &TargetNames,
											  string &excludeName,int &foundIdx)
{
  StripWhiteSpace(excludeName); // KJD a little extra paranoia while testing. 

  string EdgeName;
  for(int i = 0;i< Edges.size();i++){
	 if (GetEdgeName(Edges[i],EdgeName)){
		StripWhiteSpace(EdgeName);  // KJD paranoia
		bool bEdgeIsExclude = (EdgeName == excludeName);
		if (TargetNames.Contains(EdgeName) && !bEdgeIsExclude){
		  foundIdx = i;
		  return(true);
		}
	 }
  }
  return(false);
}


//-----------------------------------------------
// * GetNodeEdges
//-----------------------------------------------
//
void
MixedOverlapGraph::GetNodeEdges(int key,vector<Edge*> &EdgePtrs)
{
  vector<int> EdgeIdxs;
  
  // Find which virtual node this name corresponds to. 
  int nodeIdx = mTI2NodeIdxMap[key];
  mNodeIdx2EIdxMap.GetValues(nodeIdx,EdgeIdxs);

  // Find them and add them to edges
  EdgePtrs.resize(EdgeIdxs.size());
  for(int i = 0;i < EdgeIdxs.size();i++){
	 EdgePtrs[i] = &(mEdges[EdgeIdxs[i]]);
  }
}



//-----------------------------------------------
// * GetNodeEdges
//-----------------------------------------------
//
void
MixedOverlapGraph::GetNodeEdges(int key,vector<Edge> &Edges)
{
  vector<int> EdgeIdxs;

  // Find which virtual node this ti corresponds to. 
  int nodeIdx = mTI2NodeIdxMap[key];
  mNodeIdx2EIdxMap.GetValues(nodeIdx,EdgeIdxs);

  // Find them and add them to edges
  Edges.resize(EdgeIdxs.size());
  for(int i = 0;i < EdgeIdxs.size();i++){
	 Edges[i] = mEdges[EdgeIdxs[i]];
  }
}


//-----------------------------------------------
// * GetTIEdges
//-----------------------------------------------
//
void
MixedOverlapGraph::GetTIEdges(string &key,vector<Edge*> &EdgePtrs)
{
  vector<int> EdgeIdxs;
  
  // Find which virtual node this name corresponds to. 
  int nodeIdx = mName2NodeIdxMap[key];
  mNodeIdx2EIdxMap.GetValues(nodeIdx,EdgeIdxs);

  // Find them and add them to edges
  EdgePtrs.resize(EdgeIdxs.size());
  for(int i = 0;i < EdgeIdxs.size();i++){
	 EdgePtrs[i] = &(mEdges[EdgeIdxs[i]]);

	 // These edges contain the nodeIdx as their sink. 
	 // We want to return edges that contain a TI as their sink. 	
	 int nodeIdx = EdgePtrs[i]->GetTI();
	 int ti = mNodeIdx2TIMap[nodeIdx];
	 EdgePtrs[i]->SetTI(ti);
  }
}


//-----------------------------------------------
// * GetTIEdges
//-----------------------------------------------
// Looks up sinks of source (key), returning Edges 
// which contain a TI number as their sink.  
// GetNodeEdges is the same except it returns edges
// with a NodeIdx, rather than a TI number, as it's
// sink. 
//
void
MixedOverlapGraph::GetTIEdges(string &key,vector<Edge> &Edges)
{
  vector<int> EdgeIdxs;
  
  // Find which virtual node this name corresponds to. 
  int nodeIdx = mName2NodeIdxMap[key];
  mNodeIdx2EIdxMap.GetValues(nodeIdx,EdgeIdxs);

  // Find them and add them to edges
  Edges.resize(EdgeIdxs.size());
  for(int i = 0;i < EdgeIdxs.size();i++){
	 Edges[i] = mEdges[EdgeIdxs[i]];

	 // These edges contain the nodeIdx as their sink. 
	 // We want to return edges that contain a TI as their sink. 	
	 int nodeIdx = Edges[i].GetTI();
	 int ti = mNodeIdx2TIMap[nodeIdx];
	 Edges[i].SetTI(ti);
  }
}

//-----------------------------------------------
// * ReadName2TIPlusInverse
//-----------------------------------------------
// Reads in edges in form MAAA1U10002 ->   gln|ti|23456{...}  gln|ti|66543 {...} 
// and also adds the inversion of those edges to the graph, edges like:
// gln|ti|23456 -> MAAA1U10002 {...}
// gln|ti|66543 -> MAAA1U10002 {...}
//
void 
MixedOverlapGraph::ReadName2TIPlusInverse(istream &fin)
{
  // Each iteration through do{} is one line of graph file. 
  do{
	 fin.getline(readbuf,READ_BUFFER_SIZE);
	 string tempLine = readbuf;
	 int offset = 0;
	 
	 string sourceName = GetNextWSDelimitedString(tempLine,offset,offset);
	 if (offset >= 0){
		StripWhiteSpace(sourceName);
		
		vector<Edge> Edges; 	 
		do{
		  int destTI = GetNextInteger(tempLine,offset,offset);
		  
		  //string destName = GetNextWSDelimitedString(tempLine,offset,offset);
		  //StripWhiteSpace(destName);
		  if (offset < 0) continue;
		  
		  // GetNextInteger gets the next integer on the line, which is to say 
		  // it finds the next string of digits (plus possibly a minus sign) 
		  // after offset and extending to the first non-digit, and returns that as an int. 
		  int span = GetNextInteger(tempLine,offset,offset);
		  int score = GetNextInteger(tempLine,offset,offset);
		  int lext = GetNextInteger(tempLine,offset,offset);
		  int rext = GetNextInteger(tempLine,offset,offset);
		  
		  // offset should point to a comma, so next character is the direction. 
		  // Brittle, of course... what if it's comma-space-dir... should maybe be a 
		  // little more cautious. 
		  char dir = tempLine[offset+1];		
		  // skip past the comma, dir, and comma
		  //offset += 2;

		  // now eat the frequency -- discard for now
		  int frequency = GetNextInteger(tempLine, offset, offset);


		  //int bidx = tempLine.find("}",offset);
		  //cout<<"braceidx = "<<bidx<<endl;

		  // offset should now point to right-brace; skip past to tab or newline
		  // If this puts us at the end of the line, record that with -1. 
		  offset+=2;
		  if (offset >=tempLine.size()) offset = -1;
		  

		  // Correction for extensions sense reversal
		  if (dir == 'f') {
		    lext = -lext;
		    rext = -rext;
		  }
		  else { // 'r'
		    int t = -lext;
		    lext = -rext;
		    rext = t;
		  }

		  //cout<<destTI<<"\t"<<span<<"\t"<<score<<"\t"<<lext<<"\t"<<rext<<"\t"<<dir<<"\t";
		  //cout<<frequency<<"\t";
		  //cout<<"linesize="<<tempLine.size()<<" offset="<<offset<<endl;
		  
		  // Add this edge to the list of edges to put in for this sourceName
		  Edge E;
		  E.SetValues(destTI,span,score,lext,rext,dir);
		  Edges.push_back(E);
		  
		}while (offset >= 0);

		// Add edges sourceName->e1,e2,e3... to graph. 
		// Also add inverse edges   e1->sourceName e2->sourceName e3->sourceName
		if (Edges.size() > 0){
		  AddEdgesAndInverse(sourceName,Edges);
		  Edges.clear();
		}
	 }
  }while(!fin.eof());
}


//----------------------------------------------
// * AddEdges
//----------------------------------------------
// Assumes edge is not already in graph
//
void 
MixedOverlapGraph::AddEdges(string &key,vector<Edge> &Edges){

  // Create the nodes corresponding to the ti's in Edges if they 
  // do not exist. 
  int ti,score,span,le,re,dir;
  vector<int> TINodeIdxs;
  TINodeIdxs.resize(Edges.size());
  for(int e = 0;e< Edges.size();e++){
	 //int ti = E[e].GetTI();
	 Edges[e].GetValues(ti,span,score,le,re,dir);

	 // If node doesn't exit, create it. 
	 if (!mTI2NodeIdxMap.Contains(ti)){
		mTI2NodeIdxMap[ti] = mNextNodeIdx;
		mNodeIdx2TIMap[mNextNodeIdx] = ti;
		TINodeIdxs[e] = mNextNodeIdx;
		mNextNodeIdx++;
	 }else{
		// Node already exists, just record it's name. 
		TINodeIdxs[e] = mTI2NodeIdxMap[ti];
	 }  
  }

  // Add key->nodeIdx and nodeIdx-> key association. 
  int keyNodeIdx;
  if (!mName2NodeIdxMap.Contains(key)){ 
	 mName2NodeIdxMap[key] = mNextNodeIdx;
	 mNodeIdx2NameMap[mNextNodeIdx] = key;
	 keyNodeIdx = mNextNodeIdx;
	 mNextNodeIdx++;
  }else{
	 keyNodeIdx = mName2NodeIdxMap[key];
  }

  // Create new edges in this graph. 
  int nextEdgeIdx = mEdges.size();
  int newSize = Edges.size()+mEdges.size();
  mEdges.resize(newSize);
  
  int idx = 0;
  for (int eIdx = nextEdgeIdx;eIdx< newSize;eIdx++){
	 // Want the edge to record the nodeIdx not the ti. 
	 Edges[idx].GetValues(ti,span,score,le,re,dir);
	 Edges[idx].SetValues(TINodeIdxs[idx],span,score,le,re,dir);
	 // Add it to the master edge list. 
	 mEdges[eIdx] = Edges[idx];
	 // Record the keyNode -> edgeIdx mapping. 
	 mNodeIdx2EIdxMap.Add(keyNodeIdx,eIdx);
	 idx++;
  }
}


//----------------------------------------------
// * AddInverseEdgesAndInverse
//----------------------------------------------
// Assumes edge is not already in graph
//
// key is the source name (sourceName-> edge1 edge2 edge3 ...) 
// 
void 
MixedOverlapGraph::AddEdgesAndInverse(string &key,vector<Edge> &Edges){

  // Create the nodes corresponding to the ti's in Edges if they 
  // do not exist. 
  int ti,score,span,le,re,dir;
  vector<int> TINodeIdxs;
  TINodeIdxs.resize(Edges.size());
  for(int e = 0;e< Edges.size();e++){
	 ti = Edges[e].GetTI();

	 // If node doesn't exit, create it. 
	 if (!mTI2NodeIdxMap.Contains(ti)){
		mTI2NodeIdxMap[ti] = mNextNodeIdx;
		mNodeIdx2TIMap[mNextNodeIdx] = ti;
		TINodeIdxs[e] = mNextNodeIdx;
		mNextNodeIdx++;
	 }else{
		// Node already exists, just record it's name. 
		TINodeIdxs[e] = mTI2NodeIdxMap[ti];
	 }  
  }

  // The source name needs to map to some integer. 
  // This mapping is handled by mName2NodeIdxMap. 
  // If this source name (key) is already in the map, 
  // then just make a note of the index, otherwise add it. 
  int keyNodeIdx;
  if (!mName2NodeIdxMap.Contains(key)){ 
	 mName2NodeIdxMap[key] = mNextNodeIdx;
	 mNodeIdx2NameMap[mNextNodeIdx] = key;
	 keyNodeIdx = mNextNodeIdx;
	 mNextNodeIdx++;
  }else{	 
	 keyNodeIdx = mName2NodeIdxMap[key];
  }

  // Create new edges in this graph. 
  int nextEdgeIdx = mEdges.size();
  int newSize = Edges.size()+mEdges.size();
  mEdges.resize(newSize);
  
  int idx = 0;
  for (int eIdx = nextEdgeIdx;eIdx< newSize;eIdx++){
	 // Want the edge to record the nodeIdx not the ti. 
	 Edges[idx].SetTI(TINodeIdxs[idx]);
	 // Add it to the master edge list. 
	 mEdges[eIdx] = Edges[idx++];
	 mNodeIdx2EIdxMap.Add(keyNodeIdx,eIdx);
  }

  // Now make space for the inverted edges
  nextEdgeIdx = mEdges.size();
  newSize = Edges.size()+mEdges.size();
  mEdges.resize(newSize);

  idx = 0;
  for(int eIdx = nextEdgeIdx;eIdx < newSize;eIdx++){

	 // Changes the values of le,re to reflect dir and switching A->B edge to B->A.
	 // idx will range from 0 to the last of the input edges.  
	 // eIdx will range from one after that to the new size. 
	 // Edge.InvertValues(newti);
	 Edges[idx].InvertValues(keyNodeIdx);
	 mEdges[eIdx] = Edges[idx];
	 mNodeIdx2EIdxMap.Add(TINodeIdxs[idx],eIdx);
	 idx++;
  }
}


//----------------------------------------------
// * GetNames
//----------------------------------------------
// Assumes edge is not already in graph
//
void 
MixedOverlapGraph::GetNames(vector<string> &Names){
  String2IntMap::iterator it;
  for(it = mName2NodeIdxMap.begin();it != mName2NodeIdxMap.end();it++){
	 // Get the children of this node. 
	 string Name = (*it).first;
	 Names.push_back(Name);
  }
}



//======================================================================================
//                                  Overlap Graph 
//======================================================================================


//-------------------------------------------
// * EdgeExists
//-------------------------------------------
//
bool
OverlapGraph::EdgeExists(string &source, string &sink)
{
  if (!mNodeMap.Contains(source)){
	 // There is no node with source as it's name so edge not in graph. 
	 return(false);
  }else{
	 int nodeIdx = mNodeMap[source];
	 OverlapNode &N = mNodes[nodeIdx];

	 if (!N.mSinkMap.Contains(sink)){
		// A node with source as name exists, but there is no edge from there 
		// with sink as it's name. 
		return(false);
	 }else{
		return(true);
	 }
  }
}


//-------------------------------------------
// * AddEdge
//-------------------------------------------
//
void 
OverlapGraph::AddEdge(string &source,string &sink,int span,int score,int le,int re,int dir)
{
  // Could be just modifying an existing edge
  if (EdgeExists(source,sink)){
	 int nodeIdx = mNodeMap[source];
	 OverlapNode &N = mNodes[nodeIdx];
	 int edgeIdx = N.mSinkMap[sink];
	 OverlapEdge &E = N.mEdges[edgeIdx];

	 E.mSpan = span;
	 E.mScore = score;
	 E.mLE = le;
	 E.mRE = re;
	 E.mDir = dir;
	 
  }else{	 
	 // If node doesn't exist, create it and the edge.   
	 if (!mNodeMap.Contains(source)){
		OverlapNode N;
		N.AddEdge(sink,span,score,le,re,dir);
		int nextIdx = mNodes.size();
		mNodeMap[source] = nextIdx;
		mNodes.push_back(N);
	 }else{
		int nodeIdx = mNodeMap[source];
		OverlapNode &N = mNodes[nodeIdx];
		N.AddEdge(sink,span,score,le,re,dir);
	 }
  }
}

//-------------------------------------------
// * GetScore
//-------------------------------------------
//
int
OverlapGraph::GetScore(string &source, string &sink)
{
  if (!EdgeExists(source,sink)){
	 return(-1);
  }else{
	 int nodeIdx = mNodeMap[source];
	 int edgeIdx = mNodes[nodeIdx].mSinkMap[sink];
	 
	 OverlapEdge &E = mNodes[nodeIdx].mEdges[edgeIdx];
	 return(E.mScore);
  }
}


//-------------------------------------------
// * Print
//-------------------------------------------
//
void
OverlapGraph::Print(ostream &fout){

  String2IntMap::iterator it;

  for(it = mNodeMap.begin();it != mNodeMap.end();it++){
	 string sourceName = (*it).first;
	 int nodeIdx = (*it).second;
	 OverlapNode &N = mNodes[nodeIdx];
	 
	 fout<<sourceName;
	 for(int i = 0;i< N.mEdges.size();i++){
		OverlapEdge &E = N.mEdges[i];
		fout<<"\t";
		fout<<E.mSink<<" {";
		fout<<E.mSpan<<",";
		fout<<E.mScore<<",";
		fout<<E.mLE<<",";
		fout<<E.mRE<<",";
		fout<<E.mDir<<"}";
	 }
	 fout<<endl;
  }
}

